package twi;

import java.util.ArrayList;
import java.util.List;

import twi.filter.DropAnonFilter;
import twi.result.table.RTable;
import twi_project.TWI;

import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntProperty;
import com.hp.hpl.jena.ontology.OntResource;
import com.hp.hpl.jena.ontology.UnionClass;
import com.hp.hpl.jena.rdf.model.RDFList;
import com.hp.hpl.jena.rdf.model.RDFNode;

public class Utils {

	public static ArrayList<String> toArray(String[] strings) {
		ArrayList<String> out = new ArrayList<String>();
		for (int i = 0; i < strings.length; i++)
			out.add(strings[i].trim());
		return out;
	}

	public static Class<?> saveCast(Class<?> cl, Object object) {
		try{
			return (Class<?>) object;
		}catch (Exception e) {
			return null;
		}
	}
	public static OntProperty getOntProperty(String name){
		List allProp = TWI.getInstance().getOntologieModel().listAllOntProperties().toList();
		for (int i = 0; i < allProp.size(); i++){
			OntProperty op = (OntProperty) allProp.get(i);
			String n = Utils.getLocalName(op);
			if (n.equals(name))
				return op;
		}
		return null;
	}
	public static List<OntProperty> getPropertyList(OntResource cl, boolean bDomain, boolean bRange) {
		ArrayList<OntProperty> out = new ArrayList<OntProperty>();
		String n = cl.getLocalName();
		List allProp = TWI.getInstance().getOntologieModel().listAllOntProperties().toList();
		for (int i = 0; i < allProp.size(); i++){
			OntProperty p = (OntProperty) allProp.get(i);
			if (bDomain){
				OntResource domain = p.getDomain();
				if (acceptProperty(domain, cl)){
					out.add(p);
					continue;
				}				
			}
			if (bRange){
				OntResource range = p.getRange();
				if (acceptProperty(range, cl)){
					out.add(p);
					continue;
				}
			}
		}
		return out;		
	}

	public static List<OntProperty> getPropertyList(Individual in) {
		return getPropertyList(in.asClass(), true, false);
	}

	public static List<OntProperty> getPropertyList(OntClass cl) {
		return getPropertyList(cl, true, false);
	}
	
	private static boolean acceptProperty(OntResource toTest, OntResource ref){
		if (toTest == null)
			return false;
		if (ref == null)
			return false;
		if (toTest.isClass()){
			OntClass ct = toTest.asClass();
			if (ct.isUnionClass()){
				RDFList oplist = ct.asUnionClass().getOperands();
				for (int j = 0; j < oplist.size(); j++){
					RDFNode op = oplist.get(j);
					if (RTable.getNodeName(op).equals(ref.getLocalName())){
						return true;
					}
				}
			}else{
				if (ct.getLocalName().equals(ref.getLocalName()))
					return true;
			}
		}
		return false;//toTest.getLocalName().equals(ref.getLocalName());
	}

	public static boolean isDomain(OntClass cl, OntProperty prop) {
		OntResource dom = prop.getDomain();
		return acceptProperty(dom, cl);
	}

	public static ArrayList<OntClass> listClasses(OntResource or, boolean subClasses, boolean individuals) {
		ArrayList<OntClass> out = new ArrayList<OntClass>();
		if (!or.isClass())
			return out;
		OntClass cl = or.asClass();
		if (cl.isUnionClass()){
			RDFList oplist = cl.asUnionClass().getOperands();
			for (int j = 0; j < oplist.size(); j++){
				RDFNode op = oplist.get(j);
				OntClass c = TWI.getInstance().getOntologieModel().getOntClass(RTable.getNodeName(op));
				if (c != null)
					out.add(c);
			}
		}else
			out.add(cl);
		
		
		if (!subClasses && !individuals)
			return out;
		ArrayList<OntClass> all = new ArrayList<OntClass>();
		for (int i = 0; i < out.size(); i++){
			List sub = out.get(i).listSubClasses(true).filterDrop(new DropAnonFilter()).toList();
			all.add(out.get(i));
			all.addAll(sub);
		}
		if (individuals){
			ArrayList<OntClass> out_i = new ArrayList<OntClass>();
			for (int i = 0; i < all.size(); i++){
				OntClass p = all.get(i);
				List l = p.listInstances().filterDrop(new DropAnonFilter()).toList();
				out_i.addAll(l);
			}
			return out_i;
		}
		return all;
	}


	public static String getLocalName(RDFNode node) {
		if (node == null)
			return "null";
		String n = null;
		try{
			if (node.isLiteral())
				n = node.asNode().getLiteralValue().toString();
			if (node.isAnon()){
				if (node instanceof OntResource){
					if (((OntResource)node).isClass()){
						OntClass oc = ((OntResource)node).asClass();
						if (oc.isUnionClass()){
							RDFList rl = oc.asUnionClass().getOperands();
							n = "";
							for (int i = 0; i < rl.size(); i++)
								if (!rl.get(i).isAnon())
									n += getLocalName(rl.get(i))+";";
						}else
							n = "";
					}else 
						n = "";
				}else
					n = node.toString();
			}
			if (node.isResource())
				n = node.asNode().getLocalName();
		}catch(Exception e){
			if (node instanceof OntClass){
				if (((OntClass)node).isUnionClass()){
					UnionClass union = ((OntClass)node).asUnionClass();
					RDFList list = union.getOperands();
					System.out.println(list);
					n = "";
					for (int i = 0; i < list.size(); i++)
						n+= getLocalName(list.get(i)) + ";";
					return n.trim();
				}
			}
		}
		return n.trim();
	}

	public static boolean isDatatypeProperty(String propertyName) {
		OntProperty property = getOntProperty(propertyName);
		if (property == null)
			return false;
		if (property instanceof OntProperty){
			return ((OntProperty)property).isDatatypeProperty();
		}
		return false;
	}


}
